﻿using Model;
using Model.Modules;
using Nest;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Model;
using System.Diagnostics;
using System.IO.Compression;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Threading;
using Utility;
using ViewModel.VM.Control;
using Proxy;

namespace ViewModel
{
    public class VM_PageDownloadTask : BaseViewModel
    {

        #region 变量
        public static surfacedetectEntities surfaceEntities;


        public DateTime Start { get { return start; } set { start = value; OnPropertyChanged(); } }
        private DateTime start;
        public DateTime End { get { return end; } set { end = value; OnPropertyChanged(); } }
        private DateTime end;


        public ObservableCollection<steeldefectinfo> SteelDefectlist { get { return steeldefectlist; } set { steeldefectlist = value; OnPropertyChanged(); } }
        private ObservableCollection<steeldefectinfo> steeldefectlist;

        public ObservableCollection<DownLoadTask> DownLoadTaskList { get; set; }

        public string Message { get { return message; } set { message = value; OnPropertyChanged(); } }
        private string message;

        public bool Complated { get; set; }

        public bool IsAdmin { get { return StaticData.IsAdmin; } }


        public int CurrentImageIndex
        {
            get { return currentImageIndex; }
            set
            {
                currentImageIndex = value;
                OnPropertyChanged();
                //imagesFactory.UpdateImage(CurrentImageIndex);
            }
        }
        private int currentImageIndex;


        public Imagedefectinfo CurrentImg
        {
            get { return currentImg; }
            set
            {
                currentImg = value; OnPropertyChanged();
            }
        }
        private Imagedefectinfo currentImg;





        ESDataHelper eshelper;
        ImagesVirtualFactory imagesFactory;
        bool isInit = false;
        TestEntitity testEntitity;
        #endregion
        //CancellationTokenSource source = new CancellationTokenSource();
        Stack<CancellationTokenSource> sourcestack = new Stack<CancellationTokenSource>();
        bool hasqueryotherpage = false;
        public VM_PageDownloadTask()
        {
            InitData();

        }

        private void InitData()
        {

            surfaceEntities = new surfacedetectEntities();
            Start = DateTime.Now.AddDays(-1);
            End = DateTime.Now;
            DownLoadTaskList = new ObservableCollection<DownLoadTask>();
            Logger.Info("SuccessInitDownLoadService");
            isInit = true;
            Complated = true;
            Task.Run(() =>
            {
                //QuerySource();
            });
            StaticData.StaticPropertyChanged += (sender, e) =>
            {
                OnPropertyChanged(nameof(IsAdmin));
            };
        }

        /// <summary>
        /// 使用dynamic根据DataTable的列名自动添加属性并赋值
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns> 
        public static Object GetDynamicClassBydt(IList<defect_type> types)
        {
            dynamic d = new System.Dynamic.ExpandoObject();
            //创建属性，并赋值。
            foreach (defect_type type in types)
            {
                (d as System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string, object>>).Add(new System.Collections.Generic.KeyValuePair<string, object>("t" + type.id.ToString(), type.name.ToString()));
            }
            return d;
        }



        public BaseCommand SearchBatchCommand { get => new BaseCommand(SearchBatchCommand_Executed); }
        public void SearchBatchCommand_Executed(object obj)
        {
            QueryBatchList();
        }
        private void QueryBatchList()
        {


        }

        public BaseCommand ConfigCommand { get => new BaseCommand(ConfigCommand_Executed); }
        public void ConfigCommand_Executed(object obj)
        {
            new VM_WindowGradeConfig().ShowDialog();
        }

        public BaseCommand AddCusotmIdCommand { get => new BaseCommand(AddCusotmIdCommand_Executed); }
        public void AddCusotmIdCommand_Executed(object obj)
        {


        }
        public BaseCommand CancelDownloadCommand
        {
            get => new BaseCommand((obj) =>
            {
                DownLoadTask task = obj as DownLoadTask;
                if (task.TaskStatus!= Model.TaskStatus.Completed) 
                    task.CancelDownload();
            });
        }
        public BaseCommand OpenFolderCommand
        {
            get => new BaseCommand((obj) =>
            {
                DownLoadTask task = obj as DownLoadTask;
                if (System.IO.Directory.Exists(task.TaskPath))
                {
                    // 使用系统默认的文件管理器打开文件夹
                    Process.Start(task.TaskPath);
                }
            });
        }


        public BaseCommand AddTaskCommand
        {
            get => new BaseCommand((obj) =>
            {
                var start = Start;
                var end = End;
                if (start.AddDays(1.1) < end)
                {
                    System.Windows.MessageBox.Show("时间间隔不能大于1天", "日期范围错误", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly);
                    //MessageBox("时间间隔不能大于1天");
                    return;
                }
                var downloadbatchs = surfaceEntities.batch.Where(t => t.insert_time >= start && t.insert_time <= end).ToList();
                if (downloadbatchs.Count == 0)
                {
                    System.Windows.MessageBox.Show("期间没有批次，无法添加任务", "无数据", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK, MessageBoxOptions.DefaultDesktopOnly);
                    return;
                }


                var downLoadTask = new DownLoadTask(async (progress, status, canceltoken) =>await DownLoadFile(downloadbatchs, progress, status, canceltoken));

                downLoadTask.TaskId = Guid.NewGuid().ToString();
                downLoadTask.TaskName = $"{Start.ToString("MMdd_HHmm")}___{End.ToString("MMdd_HHmm")}";
                downLoadTask.TaskPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\DownloadFolder\";
                DownLoadTaskList.Add(downLoadTask);
                _ = downLoadTask.StartDownloadAsync();
                

            });
        }

        public async Task DownLoadFile(IList<batch> batchs, IProgress<double> progress, IProgress<Model.TaskStatus> status, CancellationToken canceltoken)
        {

            //开始创建压缩包并写入
            string exportPath =System.Environment.GetFolderPath( Environment.SpecialFolder.Desktop)+ @"\DownloadFolder\";
            if (!Directory.Exists(exportPath))
            {
                Directory.CreateDirectory(exportPath);
            }
            string zipFilePath = exportPath + $"{Start.ToString("MMdd_HHmm")}___{End.ToString("MMdd_HHmm")}.zip";
            while (File.Exists(zipFilePath))
            {
                zipFilePath = zipFilePath.Replace(".zip", "_1.zip");
            }
            using (FileStream zipToCreate = new FileStream(zipFilePath, FileMode.Create))
            {
                using (ZipArchive archive = new ZipArchive(zipToCreate, ZipArchiveMode.Create))
                {
                    for (int i = 0; i < batchs.Count; i++)
                    {
                        if (canceltoken.IsCancellationRequested)
                        {
                            break;
                        }
                        var batch = batchs[i];
                        // 报告进度
                        progress.Report(i * 100.0 / batchs.Count);
                        //压缩包内创建子文件夹，以批次ID命名
                        string entryFolderName = batch.main_id + "/";
                        archive.CreateEntry(entryFolderName);

                        var defectdatahelper = new DefectDataHelper();
                        var defectinfos = await new ESDataHelper().GetAllImageDefectsByMainID(batch.main_id);
                        var allimageinfos = (await new ESDataHelper().GetAllImagesByMainID(batch.main_id));
                        var imageIds = defectinfos.Select(t => t.image_id).Concat(defectinfos.Select(t => t.image2_id)).Concat(defectinfos.Select(t => t.image3_id)).Distinct().ToArray();
                        var imageinfos = allimageinfos.Where(t => imageIds.Contains(t.id)).ToList();

                        var defectjson = JsonConvert.SerializeObject(defectinfos);
                        CreatTxtInZip(archive, entryFolderName + "defect.json", defectjson);

                        var imagejson = JsonConvert.SerializeObject(imageinfos);
                        CreatTxtInZip(archive, entryFolderName + "image.json", imagejson);

                        var batchjson = JsonConvert.SerializeObject(batch);
                        CreatTxtInZip(archive, entryFolderName + "batch.json", batchjson);

                        string logstr = "";
                        if (batch.img_status != "dropped")
                        {
                            for (int n = 0; n < imageinfos.Count; n++)
                            {
                                if (canceltoken.IsCancellationRequested)
                                {
                                    logstr += $"用户取消下载\r\n";
                                    break;
                                }
                                //if (StaticData.DataBase == DataFrom.Test)
                                //{
                                //    // 模拟下载延迟
                                //    System.Threading.Thread.Sleep(5);
                                //}
                                //else
                                {
                                    var iamge = imageinfos[n];
                                    var smbPath = iamge.image_url.Replace('/', '\\');
                                    if (File.Exists(smbPath))
                                    {
                                        string entryName = entryFolderName +StaticData.ImageTypeList.Where(t=>t.id==iamge.type).FirstOrDefault()?.name+"_"+ iamge.type + Path.GetFileName(smbPath);

                                        using (Stream fileStream = File.OpenRead(smbPath))
                                        {
                                            ZipArchiveEntry entry = archive.CreateEntry(entryName);
                                            using (Stream entryStream = entry.Open())
                                            {
                                                fileStream.CopyTo(entryStream);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        logstr += $"未找到文件: {smbPath}\r\n";
                                    }
                                }

                                // 实时进度=当前批次总进度+当前批次内进度
                                progress.Report((i + (double)n / imageinfos.Count) * 100.0 / batchs.Count);
                            }
                        }
                        else
                        {
                            for(int n = 0; n < defectinfos.Count; n++)
                            {
                                if (canceltoken.IsCancellationRequested)
                                {
                                    logstr += $"用户取消下载\r\n";
                                    break;
                                }
                                //if (StaticData.DataBase == DataFrom.Test)
                                //{
                                //    // 模拟下载延迟
                                //    System.Threading.Thread.Sleep(5);
                                //}
                                //else
                                {
                                    var defect = defectinfos[n];
                                    var smbPath = defect.crop_image_url.Replace('/', '\\');
                                    if (File.Exists(smbPath))
                                    {
                                        string entryName = entryFolderName + Path.GetFileName(smbPath);

                                        using (Stream fileStream = File.OpenRead(smbPath))
                                        {
                                            ZipArchiveEntry entry = archive.CreateEntry(entryName);
                                            using (Stream entryStream = entry.Open())
                                            {
                                                fileStream.CopyTo(entryStream);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        logstr += $"未找到文件: {smbPath}\r\n";
                                    }
                                }

                                // 实时进度=当前批次总进度+当前批次内进度
                                progress.Report((i + (double)n / defectinfos.Count) * 100.0 / batchs.Count);
                            }
                            
                        }


                        CreatTxtInZip(archive, entryFolderName + "log.txt", logstr);

                    }
                    progress.Report(100);
                    if(canceltoken.IsCancellationRequested)
                        status.Report(Model.TaskStatus.Cancelled);
                    else
                    status.Report(Model.TaskStatus.Completed);
                }
            }
        }

        public void CreatTxtInZip(ZipArchive archive, string entryName, string entryContent)
        {
            //在子文件夹内创建txt文件
            ZipArchiveEntry entry = archive.CreateEntry(entryName);
            using (StreamWriter writer = new StreamWriter(entry.Open()))
            {
                writer.Write(entryContent);
            }
        }

    }
}
